package com.rp.common.utils;

/**
 * 类说明:
 *
 * @author ****
 * @date 2019/12/31 11:23  新建
 */

public class ModBusCode {
    public static void main(String[] args) {
        dealResponse("060F0000000401FF3F30");

        System.out.println(writeSingleCoil(2,0,1));
//        System.out.println(readCoils(3,19,37));
//        System.out.println(readDiscreteInputs(3,19,37));
//        System.out.println(readHoldingRegisters(3,19,37));
//        System.out.println(readInputRegisters(3,19,37));
//        System.out.println(writeSingleRegister(3,19,37));
//        byte[] bytes={1,1,0,0};
//        System.out.println(bytes.length);
//        System.out.println(writeMultipleCoils(6,0,bytes));
    }

    //读取从设备的线圈或离散量输出的状态,功能码0x01
    public static String readCoils(int slaveAddress, int startAddress, int quantity) throws InterruptedException {
        StringBuilder stringBuilder= new StringBuilder("");
        stringBuilder.append(decimalToHex(slaveAddress,2))//从站地址
                .append("01")//功能码
                .append(decimalToHex(startAddress,4))//起始地址低位
                .append(decimalToHex(quantity,4));//寄存器数量
        String code1 = CRCCheck(stringBuilder.toString());
      return code1;
    }
    //读取从设备的离散输入,功能码02
    public static String readDiscreteInputs(int slaveAddress,int startAddress,int quantity) throws InterruptedException {
        StringBuilder stringBuilder= new StringBuilder("");
        stringBuilder.append(decimalToHex(slaveAddress,2))//从站地址
                .append("02")//功能码
                .append(decimalToHex(startAddress,4))//起始地址低位
                .append(decimalToHex(quantity,4));//寄存器数量
        return CRCCheck(stringBuilder.toString());
    }
    //读取保持寄存器值，功能码03
    public static String readHoldingRegisters(String id,int slaveAddress,int startAddress,int quantity) throws InterruptedException {
        StringBuilder stringBuilder= new StringBuilder("");
        stringBuilder.append(decimalToHex(slaveAddress,2))//从站地址
                .append("03")//功能码
                .append(decimalToHex(startAddress,4))//起始地址低位
                .append(decimalToHex(quantity,4));//寄存器数量
        String code1 = CRCCheck(stringBuilder.toString());
        return CRCCheck(stringBuilder.toString());
    }
    //读取输入寄存器的值,功能码04
    public static String readInputRegisters(String id,int slaveAddress,int startAddress,int quantity) throws InterruptedException {
        StringBuilder stringBuilder= new StringBuilder("");
        stringBuilder.append(decimalToHex(slaveAddress,2))//从站地址
                .append("04")//功能码
                .append(decimalToHex(startAddress,4))//起始地址低位
                .append(decimalToHex(quantity,4));//寄存器数量
        String code1 = CRCCheck(stringBuilder.toString());
        return CRCCheck(stringBuilder.toString());
    }
    //写单个线圈寄存器的状态,代码0x05
    public static String writeSingleCoil(int slaveAddress,int address,int state){
        StringBuilder stringBuilder= new StringBuilder("");
        stringBuilder.append(decimalToHex(slaveAddress,2))//从站地址
                .append("05")//功能码
                .append(decimalToHex(address,4));//起始地址低位
        if(state!=0){
            stringBuilder.append("FF");//变更位高位
        }
        else {
            stringBuilder.append("00");//变更位高位
        }
        stringBuilder.append("00");//变更位低位
        return CRCCheck(stringBuilder.toString());
    }
    //写单个保持寄存器,功能码 06
    public static String writeSingleRegister(int slaveAddress,int address,int state){
        StringBuilder stringBuilder= new StringBuilder("");
        stringBuilder.append(decimalToHex(slaveAddress,2))//从站地址
                .append("06")//功能码
                .append(decimalToHex(address,4))//起始地址
                .append(decimalToHex(state,4));//变更数据
        return CRCCheck(stringBuilder.toString());
    }
    //写多个线圈，功能码0F
    public static String writeMultipleCoils(int slaveAddress,int address,byte[] state){
        StringBuilder stringBuilder= new StringBuilder("");
        bytesToInt(state);
        stringBuilder.append(decimalToHex(slaveAddress,2))//从站地址
                .append("0F")//功能码
                .append(decimalToHex(address,4))//起始地址
                .append(decimalToHex(state.length,4))//寄存器数
                .append(decimalToHex(state.length/4,2))//变更数据的字节数
                .append(decimalToHex(bytesToInt(state),state.length/2));//变更的数据
        System.out.println(stringBuilder.toString());
        return CRCCheck(stringBuilder.toString());
    }
    //写多个保持寄存器
    public static String writeMultipleRegisters(int slaveAddress,int address,byte[] state){
        StringBuilder stringBuilder= new StringBuilder("");
        stringBuilder.append(decimalToHex(slaveAddress,2))//从站地址
                .append("10")//功能码
                .append(decimalToHex(address,4))//起始地址
                .append(decimalToHex(state.length,4))//寄存器数
                .append(decimalToHex(state.length/4,2))//变更数据的字节数
                .append(decimalToHex(bytesToInt(state),state.length/2));//变更的数据
        System.out.println(stringBuilder.toString());
        return CRCCheck(stringBuilder.toString());
    }
    public static String CRCCheck(String response) {
        // 0x02 05 00 03 FF 00 , crc16=7C 09	01 04 00 00 00 01
        byte[] byy = hexStringToBytes(response);
        //String str = new String(response.getBytes(), "UTF-8");
        int crc = calcCrc16(byy);
        //System.out.println(String.format("0x%04x", crc));
        String ztr = String.format("0x%04x", crc).replace("0x", "").toUpperCase();
        String newstr = ztr.substring(2, 4) + ztr.substring(0, 2);
        response = response + newstr;
        //System.out.println(response);
        return response;
    }
    //处理响应报文函数
    public static String dealResponse(String resCode){

        byte[] bytes = hexStringToBytes(resCode);
        switch (bytes[1]){
            case 1:{

            }
        }
        return "";
    }
    //读取从设备的线圈或离散量输出的状态,功能码0x01
    public static String dealReadCoils(String code){
        StringBuilder stringBuilder= new StringBuilder("");

        return CRCCheck(stringBuilder.toString());
    }
    static byte[] crc16_tab_h = { (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0,
            (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1,
            (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1,
            (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0,
            (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1,
            (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0,
            (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0,
            (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1,
            (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1,
            (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0,
            (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0,
            (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1,
            (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0,
            (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1,
            (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1,
            (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0,
            (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1,
            (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0,
            (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0,
            (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1,
            (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0,
            (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1,
            (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1,
            (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0,
            (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0,
            (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1,
            (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1,
            (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0,
            (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1,
            (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0,
            (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0,
            (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1,
            (byte) 0x81, (byte) 0x40 };

    static byte[] crc16_tab_l = { (byte) 0x00, (byte) 0xC0, (byte) 0xC1, (byte) 0x01, (byte) 0xC3, (byte) 0x03,
            (byte) 0x02, (byte) 0xC2, (byte) 0xC6, (byte) 0x06, (byte) 0x07, (byte) 0xC7, (byte) 0x05, (byte) 0xC5,
            (byte) 0xC4, (byte) 0x04, (byte) 0xCC, (byte) 0x0C, (byte) 0x0D, (byte) 0xCD, (byte) 0x0F, (byte) 0xCF,
            (byte) 0xCE, (byte) 0x0E, (byte) 0x0A, (byte) 0xCA, (byte) 0xCB, (byte) 0x0B, (byte) 0xC9, (byte) 0x09,
            (byte) 0x08, (byte) 0xC8, (byte) 0xD8, (byte) 0x18, (byte) 0x19, (byte) 0xD9, (byte) 0x1B, (byte) 0xDB,
            (byte) 0xDA, (byte) 0x1A, (byte) 0x1E, (byte) 0xDE, (byte) 0xDF, (byte) 0x1F, (byte) 0xDD, (byte) 0x1D,
            (byte) 0x1C, (byte) 0xDC, (byte) 0x14, (byte) 0xD4, (byte) 0xD5, (byte) 0x15, (byte) 0xD7, (byte) 0x17,
            (byte) 0x16, (byte) 0xD6, (byte) 0xD2, (byte) 0x12, (byte) 0x13, (byte) 0xD3, (byte) 0x11, (byte) 0xD1,
            (byte) 0xD0, (byte) 0x10, (byte) 0xF0, (byte) 0x30, (byte) 0x31, (byte) 0xF1, (byte) 0x33, (byte) 0xF3,
            (byte) 0xF2, (byte) 0x32, (byte) 0x36, (byte) 0xF6, (byte) 0xF7, (byte) 0x37, (byte) 0xF5, (byte) 0x35,
            (byte) 0x34, (byte) 0xF4, (byte) 0x3C, (byte) 0xFC, (byte) 0xFD, (byte) 0x3D, (byte) 0xFF, (byte) 0x3F,
            (byte) 0x3E, (byte) 0xFE, (byte) 0xFA, (byte) 0x3A, (byte) 0x3B, (byte) 0xFB, (byte) 0x39, (byte) 0xF9,
            (byte) 0xF8, (byte) 0x38, (byte) 0x28, (byte) 0xE8, (byte) 0xE9, (byte) 0x29, (byte) 0xEB, (byte) 0x2B,
            (byte) 0x2A, (byte) 0xEA, (byte) 0xEE, (byte) 0x2E, (byte) 0x2F, (byte) 0xEF, (byte) 0x2D, (byte) 0xED,
            (byte) 0xEC, (byte) 0x2C, (byte) 0xE4, (byte) 0x24, (byte) 0x25, (byte) 0xE5, (byte) 0x27, (byte) 0xE7,
            (byte) 0xE6, (byte) 0x26, (byte) 0x22, (byte) 0xE2, (byte) 0xE3, (byte) 0x23, (byte) 0xE1, (byte) 0x21,
            (byte) 0x20, (byte) 0xE0, (byte) 0xA0, (byte) 0x60, (byte) 0x61, (byte) 0xA1, (byte) 0x63, (byte) 0xA3,
            (byte) 0xA2, (byte) 0x62, (byte) 0x66, (byte) 0xA6, (byte) 0xA7, (byte) 0x67, (byte) 0xA5, (byte) 0x65,
            (byte) 0x64, (byte) 0xA4, (byte) 0x6C, (byte) 0xAC, (byte) 0xAD, (byte) 0x6D, (byte) 0xAF, (byte) 0x6F,
            (byte) 0x6E, (byte) 0xAE, (byte) 0xAA, (byte) 0x6A, (byte) 0x6B, (byte) 0xAB, (byte) 0x69, (byte) 0xA9,
            (byte) 0xA8, (byte) 0x68, (byte) 0x78, (byte) 0xB8, (byte) 0xB9, (byte) 0x79, (byte) 0xBB, (byte) 0x7B,
            (byte) 0x7A, (byte) 0xBA, (byte) 0xBE, (byte) 0x7E, (byte) 0x7F, (byte) 0xBF, (byte) 0x7D, (byte) 0xBD,
            (byte) 0xBC, (byte) 0x7C, (byte) 0xB4, (byte) 0x74, (byte) 0x75, (byte) 0xB5, (byte) 0x77, (byte) 0xB7,
            (byte) 0xB6, (byte) 0x76, (byte) 0x72, (byte) 0xB2, (byte) 0xB3, (byte) 0x73, (byte) 0xB1, (byte) 0x71,
            (byte) 0x70, (byte) 0xB0, (byte) 0x50, (byte) 0x90, (byte) 0x91, (byte) 0x51, (byte) 0x93, (byte) 0x53,
            (byte) 0x52, (byte) 0x92, (byte) 0x96, (byte) 0x56, (byte) 0x57, (byte) 0x97, (byte) 0x55, (byte) 0x95,
            (byte) 0x94, (byte) 0x54, (byte) 0x9C, (byte) 0x5C, (byte) 0x5D, (byte) 0x9D, (byte) 0x5F, (byte) 0x9F,
            (byte) 0x9E, (byte) 0x5E, (byte) 0x5A, (byte) 0x9A, (byte) 0x9B, (byte) 0x5B, (byte) 0x99, (byte) 0x59,
            (byte) 0x58, (byte) 0x98, (byte) 0x88, (byte) 0x48, (byte) 0x49, (byte) 0x89, (byte) 0x4B, (byte) 0x8B,
            (byte) 0x8A, (byte) 0x4A, (byte) 0x4E, (byte) 0x8E, (byte) 0x8F, (byte) 0x4F, (byte) 0x8D, (byte) 0x4D,
            (byte) 0x4C, (byte) 0x8C, (byte) 0x44, (byte) 0x84, (byte) 0x85, (byte) 0x45, (byte) 0x87, (byte) 0x47,
            (byte) 0x46, (byte) 0x86, (byte) 0x82, (byte) 0x42, (byte) 0x43, (byte) 0x83, (byte) 0x41, (byte) 0x81,
            (byte) 0x80, (byte) 0x40 };

    /**
     * 计算CRC16校验
     *
     * @param data
     *            需要计算的数组
     * @return CRC16校验值
     */
    public static int calcCrc16(byte[] data) {
        return calcCrc16(data, 0, data.length);
    }

    /**
     * 计算CRC16校验
     *
     * @param data
     *            需要计算的数组
     * @param offset
     *            起始位置
     * @param len
     *            长度
     * @return CRC16校验值
     */
    public static int calcCrc16(byte[] data, int offset, int len) {
        return calcCrc16(data, offset, len, 0xffff);
    }

    /**
     * 计算CRC16校验
     *
     * @param data
     *            需要计算的数组
     * @param offset
     *            起始位置
     * @param len
     *            长度
     * @param preval
     *            之前的校验值
     * @return CRC16校验值
     */
    public static int calcCrc16(byte[] data, int offset, int len, int preval) {
        int ucCRCHi = (preval & 0xff00) >> 8;
        int ucCRCLo = preval & 0x00ff;
        int iIndex;
        for (int i = 0; i < len; ++i) {
            iIndex = (ucCRCLo ^ data[offset + i]) & 0x00ff;
            ucCRCLo = ucCRCHi ^ crc16_tab_h[iIndex];
            ucCRCHi = crc16_tab_l[iIndex];
        }
        return ((ucCRCHi & 0x00ff) << 8) | (ucCRCLo & 0x00ff) & 0xffff;
    }

    public static byte[] hexStringToBytes(String hexString) {
        if (hexString == null || hexString.equals("")) {
            return null;
        }
        hexString = hexString.toUpperCase();
        int length = hexString.length() / 2;
        char[] hexChars = hexString.toCharArray();
        byte[] d = new byte[length];
        for (int i = 0; i < length; i++) {
            int pos = i * 2;
            d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
        }
        return d;
    }
    public static byte charToByte(char c) {
        return (byte) "0123456789ABCDEF".indexOf(c);
    }
    public static int bytesToInt(byte[] bytes){
        int a = 0;
        int i=bytes.length-1;
        for (;i>=0;i--){
            System.out.println(i);
            a= (a<<1)+bytes[i];
        }
        return a;
    }
    public static String decimalToHex(int decimal,int length) {
        String hex = "";
        int i=0;
//		if(decimal==0) return "00";
        while(decimal != 0) {
            i++;
            length--;
            int hexValue = decimal % 16;
            hex = toHexChar(hexValue) + hex;
            decimal = decimal / 16;

        }
        for (;length>0;length--){
            hex="0"+hex;
        }
        //获得偶数为的16进制字符串
//		if(i%2!=0) hex="0"+hex;

        return  hex;
    }
    //将0~15的十进制数转换成0~F的十六进制数
    public static char toHexChar(int hexValue) {
        if(hexValue <= 9 && hexValue >= 0)
            return (char)(hexValue + '0');
        else
            return (char)(hexValue - 10 + 'A');
    }
}



















